//
// Created by entaoyang@163.com on 2021/2/9.
//

import Foundation
import CoreGraphics

#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif


public typealias Rect = CGRect
public typealias Size = CGSize

public extension CGSize {

    init(_ sz: CGFloat) {
        self.init(width: sz, height: sz)
    }


    init(_ w: CGFloat, _ h: CGFloat) {
        self.init(width: w, height: h)
    }

}

public extension Size {
    func add(_ sz: Size) -> Size {
        Size(self.width + sz.width, self.height + sz.height)
    }

    func add(_ w: CGFloat, _ h: CGFloat) -> Size {
        Size(self.width + w, self.height + h)
    }

    var ceiled: Size {
        Size(ceil(self.width), ceil(self.height))
    }
}

public extension CGRect {
    //	static var zero: CGRect {
    //		return CGRect(x: 0, y: 0, width: 0, height: 0)
    //	}
    static var one: CGRect {
        CGRect(x: 0, y: 0, width: 1, height: 1)
    }

    static func sized(_ sz: CGSize) -> CGRect {
        sized(sz.width, sz.height)
    }

    static func sized(_ w: CGFloat) -> CGRect {
        sized(w, w)
    }

    static func sized(_ w: CGFloat, _ h: CGFloat) -> CGRect {
        CGRect(x: 0, y: 0, width: w, height: h)
    }

    static func make(_ x: CGFloat, _ y: CGFloat, _ w: CGFloat, _ h: CGFloat) -> CGRect {
        CGRect(x: x, y: y, width: w, height: h)
    }
}

public extension CGRect {

    func from(x: CGFloat, y: CGFloat) -> CGRect {
        CGRect(x: x, y: y, width: self.size.width, height: self.size.height)
    }

    func from(_ pt: CGPoint) -> CGRect {
        CGRect(x: pt.x, y: pt.y, width: self.size.width, height: self.size.height)
    }

    var center: CGPoint {
        CGPoint(x: (self.minX + self.maxX) / 2, y: (self.minY + self.maxY) / 2)
    }
}


public extension EdgeInset {

    static func X(left: CGFloat, right: CGFloat) -> EdgeInset {
        EdgeInset(left: left, top: 0, right: right, bottom: 0)
    }

    static func X(hor: CGFloat) -> EdgeInset {
        EdgeInset(left: hor, top: 0, right: hor, bottom: 0)
    }

    init(left: CGFloat, top: CGFloat, right: CGFloat, bottom: CGFloat) {
        self.init(top: top, left: left, bottom: bottom, right: right)
    }

    init(_ hor: CGFloat, _ ver: CGFloat) {
        self.init(top: ver, left: hor, bottom: ver, right: hor)
    }

    init(hor: CGFloat, ver: CGFloat) {
        self.init(top: ver, left: hor, bottom: ver, right: hor)
    }

    init(all: CGFloat) {
        self.init(top: all, left: all, bottom: all, right: all)
    }

    func hor(left: CGFloat, right: CGFloat) -> EdgeInset {
        EdgeInset(left: left, top: top, right: right, bottom: bottom)
    }

    func hor(_ hor: CGFloat) -> EdgeInset {
        EdgeInset(left: hor, top: top, right: hor, bottom: bottom)
    }

    func ver(top: CGFloat, bottom: CGFloat) -> EdgeInset {
        EdgeInset(left: self.left, top: top, right: self.right, bottom: bottom)
    }

    func ver(_ ver: CGFloat) -> EdgeInset {
        EdgeInset(left: self.left, top: ver, right: self.right, bottom: ver)
    }

    var horSpace: CGFloat {
        self.left + self.right
    }
    var verSpace: CGFloat {
        self.top + self.bottom
    }
}

@objcMembers
public class Edge: NSObject, Codable {
    public var left: CGFloat
    public var right: CGFloat
    public var top: CGFloat
    public var bottom: CGFloat

    public init(left: CGFloat = 0, top: CGFloat = 0, right: CGFloat = 0, bottom: CGFloat = 0) {
        self.left = left
        self.top = top
        self.right = right
        self.bottom = bottom
    }

    public override var description: String {
        "Edge{left:\(left), top:\(top), right:\(right), bottom:\(bottom)}"
    }
}

public extension Edge {
    static func X(_ lr: CGFloat) -> Edge {
        let e = Edge()
        e.left = lr
        e.right = lr
        return e
    }

    static func Y(_ tb: CGFloat) -> Edge {
        let e = Edge()
        e.top = tb
        e.bottom = tb
        return e
    }

    var horSpace: CGFloat {
        left + right
    }
    var verSpace: CGFloat {
        top + bottom
    }

    @discardableResult
    func all(_ v: CGFloat) -> Edge {
        self.left = v
        self.right = v
        self.top = v
        self.bottom = v
        return self
    }


    @discardableResult
    func hor(_ left: CGFloat, _ right: CGFloat) -> Edge {
        self.left = left
        self.right = right
        return self
    }

    @discardableResult
    func hor(_ lr: CGFloat) -> Edge {
        self.left = lr
        self.right = lr
        return self
    }

    @discardableResult
    func ver(_ top: CGFloat, _ bottom: CGFloat) -> Edge {
        self.top = top
        self.bottom = bottom
        return self
    }

    @discardableResult
    func ver(_ tb: CGFloat) -> Edge {
        self.top = tb
        self.bottom = tb
        return self
    }

    var edgeInsets: EdgeInset {
        EdgeInset(top: top, left: left, bottom: bottom, right: right)
    }

    static let zero: Edge = Edge()

    static func from(_ edgeInsets: EdgeInset) -> Edge {
        Edge(left: edgeInsets.left, top: edgeInsets.top, right: edgeInsets.right, bottom: edgeInsets.bottom)
    }

    static func ==(lhs: Edge, rhs: Edge) -> Bool {
        lhs.left == rhs.left && lhs.right == rhs.right && lhs.top == rhs.right && lhs.bottom == rhs.bottom
    }

}

public extension Rect {

    func inset(_ edge: Edge) -> Rect {
        Rect(x: self.minX + edge.left, y: self.minY + edge.top, width: self.width - edge.left - edge.right, height: self.height - edge.top - edge.bottom)
    }

    func outset(_ e: EdgeInset) -> Rect {
        Rect(x: self.minX - e.left, y: self.minY - e.top, width: self.width + e.horSpace, height: self.height + e.verSpace)
    }
}

